package com.chpn.log.service.impl;

import cn.hutool.core.util.RandomUtil;
import cn.hutool.json.JSONUtil;
import com.chpn.log.entity.TagEntity;
import com.chpn.log.entity.TagGroup;
import com.chpn.log.service.IdIncrementService;
import com.chpn.log.service.LogService;
import com.chpn.log.util.Constant;
import com.chpn.log.write.WriteLogA;
import com.chpn.log.write.WriteLogB;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.Maps;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;

import javax.annotation.PostConstruct;
import java.util.Map;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;

@Service
public class LogServiceImpl implements LogService {

    private static final ImmutableMap<Integer, String> tagMap = ImmutableMap.of(0, "A", 1, "B");
    private static final Logger logger = LoggerFactory.getLogger(LogServiceImpl.class);


//    private final Map<Integer, TagGenerator> tagGeneratorMap = Maps.newHashMap();

    private final Map<Integer, ThreadPoolExecutor> executorMap = Maps.newHashMap();

    @Value("${log.generator.threadNum}")
    private int threadNum;

    @Value("${log.generator.num}")
    private Long lineNum;

    @Value("${log.id.cached}")
    private Boolean cached;

    @Autowired
    private StringRedisTemplate stringRedisTemplate;

    @PostConstruct
    public void init() {
        for (int i = 1; i <= threadNum; i++) {

            executorMap.put(i,  new ThreadPoolExecutor(1, 1,
                    0L, TimeUnit.MILLISECONDS,
                    new LinkedBlockingQueue<>(1024)));
        }
    }

    @Override
    public void crate() {
        Constant.map.put("startTime", System.currentTimeMillis());
        ThreadPoolExecutor threadPoolExecutor = new ThreadPoolExecutor(5, 10,
                0L, TimeUnit.MILLISECONDS,
                new LinkedBlockingQueue<>(100000));
        for (int i = 0; i < lineNum; i++) {
            logger.info("create........:{}", i);
            int finalI = i;
            threadPoolExecutor.execute(() -> {
                int index = (finalI % threadNum) + 1;
                TagGroup tag = createTag();
                executorMap.get(index).execute(() -> process(tag));
            });
        }

    }


    @Autowired
    private IdIncrementService idIncrementService;

    private static String getTagValue() {
        int tag = RandomUtil.randomInt(0, 2);
        return tagMap.get(tag);
    }

    private TagGroup createTag() {
        Long id;
        if (cached) {   // startTime:1722513970299, endTime:1722514004877, count:34578 缓存保存数据，100000 条数据，处理耗时，30s左右
            id = stringRedisTemplate.opsForValue().increment(Constant.ID_NAME_LOG_GENERATOR);
        } else {// startTime:1722514164340, endTime:1722514746606, count:582266 数据库保存数据，100000 条数据，处理耗时， 582s左右
            id = idIncrementService.getIncrement(Constant.ID_NAME_LOG_GENERATOR);
        }


        TagEntity tagEntity1 = new TagEntity();
        tagEntity1.setId(id);
        tagEntity1.setTag(getTagValue());

        TagEntity tagEntity2 = new TagEntity();
        tagEntity2.setId(id);
        tagEntity2.setTag(getTagValue());
        return new TagGroup().setTagEntityA(tagEntity1).setTagEntityB(tagEntity2);

    }
    private void process(TagGroup tagGroup){
        logger.info("process:{}", JSONUtil.toJsonStr(tagGroup));
        WriteLogA.write(tagGroup.getTagEntityA());
        WriteLogB.write(tagGroup.getTagEntityB());
//        if (tagGroups.isEmpty()){
//            long currentTime = System.currentTimeMillis();
//            logger.info("startTime:{}, endTime:{}, count:{}", Constant.map.get("startTime"), currentTime, currentTime - Constant.map.get("startTime"));
//        }
    }


}
